home *** CD-ROM | disk | FTP | other *** search
/ CICA 1995 September (Japanese) / CICA Shareware for Windows CD-ROM (Walnut Creek) (September 1995) (Japanese) (Disc 2).iso / disc2 / nt / ntperf.exe / PERFTOOLS / SRC / PERFMON / INTRLINE.C_ / INTRLINE.C
Encoding:
C/C++ Source or Header  |  1993-05-15  |  26.0 KB  |  916 lines

  1. /*
  2. ==============================================================================
  3.  
  4.   Application:
  5.  
  6.             Microsoft Windows NT (TM) Performance Monitor
  7.  
  8.   File:
  9.             intrline.c -- IntervalLine custom control.
  10.  
  11.   Copyright 1992, Microsoft Corporation. All Rights Reserved.
  12. ==============================================================================
  13. */
  14.  
  15.  
  16. /*
  17.  
  18.  
  19. Basic Information
  20. -----------------
  21.    
  22. An ILine (Interval Line) control is a horizontally-sliding device; the user 
  23. can slide the start position and end position independently by dragging 
  24. either "grab" bar, or move them simultaneously by dragging the center grab
  25. bar. An ILine control is used in the Input Log dialog of Perfmon, but could
  26. be used anywhere. The control allows the user to specify the start, end and 
  27. duration of playback within the range of previously-logged data.
  28.  
  29.  
  30. ILine Parts
  31. -----------
  32.  
  33.      iBeginValue                                            iEndValue
  34.      |      iStartValue                        iStopValue           |
  35.      |      |                                           |           |
  36.      v      v                                           v           v
  37.      +------+-+---------------------------------------+-+-----------+
  38.      |      |X|                                       |X|           |
  39.      |      |X|                                       |X|           |
  40.      +------+-+---------------------------------------+-+-----------+
  41.              ^                    ^                    ^
  42.              Start grab bar       Center grab bar      Stop grab bar
  43.  
  44.  
  45. ILine Terminology
  46. -----------------
  47.  
  48. All external routines are designated by the prefix ILine-.
  49. Internal routines are designated by the prefix IL-.
  50.  
  51. The suffix -Value represents an integer in the user-supplied domain.
  52. The suffix -Pixel represents an integer location on the screen.
  53.  
  54. Note that the range of the IntervalLine is represented by "Begin" and 
  55. "End", while the the currently selected interval is represented by
  56. "Start" and "Stop".
  57.  
  58.  
  59. Implementation Notes
  60. --------------------
  61.  
  62. ILine is a custom control, but does not have all the messages 
  63. normally associated with a full-fledged control type like "button". 
  64. In particular, it doesn't have a keyboard interface or ask it's parent
  65. for color choices. It also doesn't have the functions needed for interfacing
  66. with the dialog editor custom control menu.
  67.  
  68. An ILine control is designed to work with an integer range of values
  69. specified by the user of the control. These values should have meaning to
  70. the caller. The caller can specify the minimum value of the range 
  71. (iBeginValue), the maximum value of the range (iEndValue), and the current
  72. starting and stopping values (iStartValue and iStopValue). 
  73.  
  74. These values are set with a function-based interface. (ILSetXXX).
  75.  
  76. The code distinguishes between the *values* for the begin, end, start, and
  77. stop, and the *pixels* which represent locations on the control for these
  78. values.
  79.  
  80. Various bits of the control style allow for changing the control's 
  81. behavior.
  82.  
  83. To allow for multiple ILine controls, all data used by each ILine
  84. instance is allocated from the heap and associated with the control.
  85. The allocation is done in OnCreate and the freeing in OnDestroy. The
  86. instance data is contained in the ILINE structure. Each message handler
  87. retrieves this instance data with the ILData function.
  88.  
  89.  
  90. To Do:
  91. ------
  92.  
  93. Add a keyboard interface?
  94. Add a double click interface?
  95. Add a focus rect?
  96. Support WM_CTLCOLOR?
  97.  
  98. */      
  99.  
  100.  
  101. //==========================================================================//
  102. //                                  Includes                                //
  103. //==========================================================================//
  104.  
  105.  
  106. #include "perfmon.h"
  107. #include "utils.h"
  108. #include "intrline.h"
  109. #include "pmemory.h"        // for MemoryXXX (mallloc-type) routines
  110.  
  111.  
  112. //==========================================================================//
  113. //                                  Constants                               //
  114. //==========================================================================//
  115.  
  116.  
  117. #define dwILineClassStyle     (CS_HREDRAW | CS_VREDRAW)
  118. #define iILineClassExtra      (0)
  119. #define iILineWindowExtra     (sizeof (PILINE))
  120. #define dwILineWindowStyle    (WS_CHILD | WS_VISIBLE) 
  121.  
  122.  
  123. #define ILModeNone            0
  124. #define ILModeLeft            1
  125. #define ILModeCenter          2
  126. #define ILModeRight           3
  127.  
  128.  
  129. //==========================================================================//
  130. //                                  Typedefs                                //
  131. //==========================================================================//
  132.  
  133.  
  134. // The instance data for each IL window.  One of these is allocated for each
  135. // window in the window's OnCreate processing and free'd in OnDestroy.
  136. typedef struct ILINESTRUCT
  137.    {  // ILINE
  138.    int            iBeginValue ;        // user-supplied lowest range
  139.    int            iEndValue ;          // user-supplied highest range
  140.    int            iStartValue ;        // current start of selected interval
  141.    int            iStopValue ;         // current end of selected interval
  142.    int            iGranularityValue ;
  143.    int            iMinimumRangeValue ;
  144.  
  145.    RECT           rectBorder ;
  146.    RECT           rectLeftBk ;
  147.    RECT           rectLeftGrab ;
  148.    RECT           rectCenterGrab ;
  149.    RECT           rectRightGrab ;
  150.    RECT           rectRightBk ;
  151.  
  152.    HBRUSH         hBrushBk ;
  153.  
  154.    POINTS         ptsMouse ;
  155.    int            iMode ;              // who is being tracked?
  156.    } ILINE ;
  157.  
  158. typedef ILINE *PILINE ;
  159.  
  160.  
  161. //==========================================================================//
  162. //                                   Macros                                 //
  163. //==========================================================================//
  164.  
  165.  
  166. // Width of the start and stob grab bars
  167. #define ILGrabWidth()      \
  168.    (xScrollThumbWidth)
  169.  
  170.  
  171. // A rectangle is "drawable" if it has both nonzero width and height
  172. #define RectDrawable(lpRect)           \
  173.    ((lpRect->right - lpRect->left) &&  \
  174.     (lpRect->bottom - lpRect->top))
  175.  
  176.  
  177. //======================================//
  178. // ILine Accessor Macros                //
  179. //======================================//
  180.  
  181. // These macros reference fields in the ILine structure and should be
  182. // used in place of direct reference to the fields. This makes the code
  183. // easier to read and allows modification of the underlying structure.
  184.  
  185. // You can use these macros to both get and set the fields.
  186.  
  187. #define ILBegin(pILine)    \
  188.    (pILine->iBeginValue)
  189.  
  190. #define ILEnd(pILine)      \
  191.    (pILine->iEndValue)
  192.  
  193. #define ILStart(pILine)    \
  194.    (pILine->iStartValue)
  195.  
  196. #define ILStop(pILine)     \
  197.    (pILine->iStopValue)
  198.  
  199. #define ILMode(pILine)     \
  200.    (pILine->iMode)
  201.  
  202.  
  203. //======================================//
  204. // ILine Pseudo-Accessor Macros         //
  205. //======================================//
  206.  
  207. // These macros are used to get values which don't correspond to a single
  208. // field. You can get the value with these macros but can't set it.
  209.  
  210. #define ILWidth(pILine)    \
  211.    (pILine->rectBorder.right)
  212.  
  213. #define ILRange(pILine)    \
  214.    (ILEnd (pILine) - ILBegin (pILine))
  215.  
  216. #define ILStartPixel(pILine) \
  217.    (pILine->rectLeftGrab.left)
  218.  
  219. #define ILStopPixel(pILine)   \
  220.    (pILine->rectRightGrab.right)
  221.  
  222.  
  223. //==========================================================================//
  224. //                              Local Functions                             //
  225. //==========================================================================//
  226.  
  227.  
  228. void static ILNotifyChange (HWND hWnd,
  229.                             PILINE pILine)
  230.    {  // ILNotifyChange
  231.    HWND           hWndParent ;
  232.  
  233.    hWndParent = WindowParent (hWnd) ;
  234.  
  235.    if (hWndParent)
  236.       SendMessage (hWndParent, WM_COMMAND, 
  237.                    (WPARAM) WindowID (hWnd),
  238.                    (LPARAM) hWnd) ;
  239.    }  // ILNotifyChange
  240.  
  241.  
  242. BOOL ILGrabRect (IN PILINE pILine, 
  243.                  OUT LPRECT lpRect)
  244. /*
  245.    Effect:        Return in lpRect the rectangle representing the position
  246.                   of the grab bar currently being tracked.
  247. */
  248.    {  // ILGrabRect
  249.    switch (ILMode (pILine))
  250.       {  // switch
  251.       case ILModeLeft:
  252.          *lpRect = pILine->rectLeftGrab ;
  253.          return (TRUE) ;
  254.          break ;
  255.  
  256.       case ILModeRight:
  257.          *lpRect = pILine->rectRightGrab ;
  258.          return (TRUE) ;
  259.          break ;
  260.  
  261.       case ILModeCenter:
  262.          *lpRect = pILine->rectCenterGrab ;
  263.          return (TRUE) ;
  264.          break ;
  265.  
  266.       case ILModeNone:
  267.          lpRect->left = 0 ;
  268.          lpRect->top = 0 ;
  269.          lpRect->right = 0 ;
  270.          lpRect->bottom = 0 ;
  271.          return (FALSE) ;
  272.          break ;
  273.       }  // switch
  274.    }  // ILGrabRect
  275.  
  276.  
  277. PILINE ILData (HWND hWndIL)
  278.    {
  279.    return ((PILINE) GetWindowLong (hWndIL, 0)) ;
  280.    }
  281.  
  282.  
  283. PILINE AllocateILData (HWND hWndIL)
  284.    {
  285.    PILINE         pILine ;
  286.  
  287.    pILine = MemoryAllocate (sizeof (ILINE)) ;
  288.    SetWindowLong (hWndIL, 0, (LONG) pILine) ;
  289.  
  290.    return (pILine) ;
  291.    }
  292.  
  293.  
  294. void static DrawGrab (HDC hDC,
  295.                       LPRECT lpRectGrab,
  296.                       BOOL bDown)
  297.    {  // DrawGrab
  298.    if (!RectDrawable (lpRectGrab))
  299.       return ;
  300.  
  301.    if (bDown)
  302.       ThreeDConcave1 (hDC, 
  303.                      lpRectGrab->left,
  304.                      lpRectGrab->top,
  305.                      lpRectGrab->right,
  306.                      lpRectGrab->bottom) ;
  307.    else
  308.       ThreeDConvex1 (hDC, 
  309.                     lpRectGrab->left,
  310.                     lpRectGrab->top,
  311.                     lpRectGrab->right,
  312.                     lpRectGrab->bottom) ;
  313.    }  // DrawGrab
  314.  
  315.  
  316. int ILValueToPixel (PILINE pILine,
  317.                     int iValue)
  318.    {
  319.    int            xPixel ;
  320.  
  321.    if (ILRange (pILine))
  322.       xPixel = MulDiv (iValue, ILWidth (pILine), ILRange (pILine)) ;
  323.    else
  324.       xPixel = 0 ;
  325.  
  326.    return (PinExclusive (xPixel, 0, pILine->rectBorder.right)) ;
  327.    }
  328.  
  329.  
  330. int ILPixelToValue (PILINE pILine,
  331.                     int xPixel)
  332.    {
  333.    int            iValue ;
  334.  
  335.    if (ILWidth (pILine))
  336.       iValue = MulDiv (xPixel, ILRange (pILine), ILWidth (pILine)) ;
  337.    else
  338.       iValue = 0 ;
  339.  
  340.    return (PinInclusive (iValue, ILBegin (pILine), ILEnd (pILine))) ;
  341.    }
  342.  
  343.  
  344. void static ILCalcPositions (HWND hWnd,
  345.                              PILINE pILine)
  346. /*
  347.    Effect:        Determine and set all of the physical rectangles of ILine,
  348.                   based on the current size of the ILine window and the 
  349.                   current logical Start, Stop, Begin, and End values.
  350. */
  351.    {  // ILCalcPositions
  352.    int            xStart, xStop ;
  353.    int            yHeight ;
  354.  
  355.    GetClientRect (hWnd, &pILine->rectBorder) ;
  356.    yHeight = pILine->rectBorder.bottom ;
  357.  
  358.    xStart = ILValueToPixel (pILine, ILStart (pILine)) ;
  359.    xStop = ILValueToPixel (pILine, ILStop (pILine)) ;
  360.  
  361.    pILine->rectLeftBk.left = 1 ;
  362.    pILine->rectLeftBk.top = 1 ;
  363.    pILine->rectLeftBk.right = xStart ;
  364.    pILine->rectLeftBk.bottom = yHeight - 1 ;
  365.  
  366.    pILine->rectLeftGrab.left = xStart ;
  367.    pILine->rectLeftGrab.top = 1 ;
  368.    pILine->rectLeftGrab.right = xStart + ILGrabWidth () ;
  369.    pILine->rectLeftGrab.bottom = yHeight - 1 ;
  370.  
  371.    pILine->rectRightBk.left = xStop ;
  372.    pILine->rectRightBk.top = 1 ;
  373.    pILine->rectRightBk.right = pILine->rectBorder.right - 1 ;
  374.    pILine->rectRightBk.bottom = yHeight - 1 ;
  375.  
  376.    pILine->rectRightGrab.left = xStop - ILGrabWidth () ;
  377.    pILine->rectRightGrab.top = 1 ;
  378.    pILine->rectRightGrab.right = xStop ;
  379.    pILine->rectRightGrab.bottom = yHeight - 1 ;
  380.  
  381.    pILine->rectCenterGrab.left = pILine->rectLeftGrab.right ;
  382.    pILine->rectCenterGrab.top = 1 ;
  383.    pILine->rectCenterGrab.right = pILine->rectRightGrab.left ;
  384.    pILine->rectCenterGrab.bottom = yHeight - 1 ;
  385.  
  386.    if (pILine->rectLeftGrab.right > pILine->rectRightGrab.left)
  387.       {
  388.       pILine->rectLeftGrab.right = pILine->rectLeftGrab.left + 
  389.                                    (xStop - xStart) / 2 ;
  390.       pILine->rectRightGrab.left = pILine->rectLeftGrab.right ;
  391.       pILine->rectCenterGrab.left = 0 ;
  392.       pILine->rectCenterGrab.right = 0 ;
  393.       }
  394.    }  // ILCalcPositions
  395.  
  396.  
  397. void static ILDraw (HDC hDC, 
  398.                     PILINE pILine,     
  399.                     LPRECT lpRectUpdate)
  400. /*
  401.    Effect:        Draw the image of pILine on hDC.  Draw at least the 
  402.                   portions within rectUpdate.
  403.  
  404.    Called By:     OnPaint, OnMouseMove.
  405. */
  406.    {  // ILDraw
  407.  
  408.    //=============================//
  409.    // Draw Border                 //
  410.    //=============================//
  411.    
  412.    FrameRect (hDC, &pILine->rectBorder, GetStockObject (BLACK_BRUSH)) ;
  413.  
  414.    //=============================//
  415.    // Draw Background             //
  416.    //=============================//
  417.  
  418.    FillRect (hDC, &pILine->rectLeftBk, pILine->hBrushBk) ;
  419.    FillRect (hDC, &pILine->rectRightBk, pILine->hBrushBk) ;
  420.  
  421.    //=============================//
  422.    // Draw Range Grabs            //
  423.    //=============================//
  424.  
  425.    DrawGrab (hDC, &pILine->rectLeftGrab, 
  426.              ILMode (pILine) == ILModeLeft) ;
  427.    DrawGrab (hDC, &pILine->rectRightGrab,
  428.              ILMode (pILine) == ILModeRight) ;
  429.  
  430.    //=============================//
  431.    // Draw Center Grab            //
  432.    //=============================//
  433.  
  434.    DrawGrab (hDC, &pILine->rectCenterGrab,
  435.              ILMode (pILine) == ILModeCenter) ;
  436.    }  // ILDraw
  437.  
  438.  
  439. void ILPageLeftRight (HWND hWnd,
  440.                       PILINE pILine,
  441.                       BOOL bLeft)
  442.    {  // ILPageLeftRight
  443.    int            iStart, iStop, iMove ;
  444.    HDC            hDC ;
  445.  
  446.    iStart = ILStart (pILine) ;
  447.    iStop = ILStop (pILine) ;
  448.  
  449.    if (ILRange (pILine) >= 10)   
  450.       iMove = ILRange (pILine) / 10 ;
  451.    else
  452.       iMove = 1 ;
  453.  
  454.    if (bLeft)
  455.       iMove = -iMove ;
  456.  
  457.    iStart += iMove ;
  458.    iStop += iMove ;
  459.  
  460.    ILineSetStart (hWnd, iStart) ;
  461.    ILineSetStop (hWnd, iStop) ;
  462.  
  463.    hDC = GetDC (hWnd) ;
  464.    ILDraw (hDC, pILine, &pILine->rectBorder) ;
  465.    ReleaseDC (hWnd, hDC) ;
  466.  
  467.    ILNotifyChange (hWnd, pILine) ;
  468.    }  // ILPageLeftRight
  469.  
  470.  
  471. void StartGrab (HWND hWnd,
  472.                 PILINE pILine)
  473.    {  // StartGrab
  474.    RECT           rectUpdate ;
  475.    HDC            hDC ;
  476.  
  477.    SetCapture (hWnd) ;
  478.    ILGrabRect (pILine, &rectUpdate) ;
  479.  
  480.    hDC = GetDC (hWnd) ;
  481.    ILDraw (hDC, pILine, &rectUpdate) ;
  482.    ReleaseDC (hWnd, hDC) ;
  483.    }  // StartGrab
  484.  
  485.  
  486. void EndGrab (HWND hWnd,
  487.               PILINE pILine)
  488. /*
  489.    Internals:     Set the mode to null after getting the grab rectangle
  490.                   so ILGrabRect knows which grab bar to get.
  491. */
  492.    {
  493.    RECT           rectUpdate ;
  494.    HDC            hDC ;
  495.  
  496.    ReleaseCapture () ;
  497.  
  498.    ILGrabRect (pILine, &rectUpdate) ;
  499.    ILMode (pILine) = ILModeNone ;
  500.  
  501.    hDC = GetDC (hWnd) ;
  502.    ILDraw (hDC, pILine, &rectUpdate) ;
  503.    ReleaseDC  (hWnd, hDC) ;
  504.    }
  505.  
  506.    
  507. //==========================================================================//
  508. //                              Message Handlers                            //
  509. //==========================================================================//
  510.  
  511.  
  512. void static OnPaint (HWND hWnd)
  513.    {
  514.    PAINTSTRUCT    ps ;
  515.    HDC            hDC ;
  516.    PILINE         pILine ;
  517.  
  518.    pILine = ILData (hWnd) ;
  519.    hDC = BeginPaint (hWnd, &ps) ;
  520.  
  521.    ILDraw (hDC, pILine, &ps.rcPaint) ;
  522.  
  523.    EndPaint (hWnd, &ps) ;
  524.    }
  525.  
  526.  
  527. void static OnCreate (HWND hWnd)
  528.    {
  529.    PILINE         pILine ;
  530.  
  531.    pILine = AllocateILData (hWnd) ;
  532.    ILBegin (pILine) =  0 ;
  533.    ILEnd (pILine) =  100 ;
  534.    ILStart (pILine) =  0 ;
  535.    ILStop (pILine) = 100 ;
  536.    ILMode (pILine) = ILModeNone ;
  537.  
  538.    pILine->hBrushBk = CreateSolidBrush (crBlue) ;
  539.    ILCalcPositions (hWnd, pILine) ;
  540.    }
  541.  
  542.  
  543. void static OnDestroy (HWND hWnd)
  544.    {
  545.    PILINE         pILine ;
  546.  
  547.    pILine = ILData (hWnd) ;
  548.  
  549.    DeleteBrush (pILine->hBrushBk) ;
  550.    MemoryFree (pILine) ;
  551.    }
  552.  
  553.  
  554. void static OnLButtonUp (HWND hWnd)
  555.    {  // OnLButtonUp
  556.    PILINE         pILine ;
  557.  
  558.    pILine = ILData (hWnd) ;
  559.  
  560.    if (ILMode (pILine) == ILModeNone)
  561.       return ;
  562.  
  563.    EndGrab (hWnd, pILine) ;
  564.    }  // OnLButtonUp
  565.  
  566.  
  567. void static OnMouseMove (HWND hWnd,
  568.                          POINTS ptsMouse)
  569. /*
  570.    Effect:        Handle any actions needed when the mouse moves in the
  571.                   ILine hWnd's client area or while the mouse is captured.
  572.                   In particular, if we are tracking one of the grab bars, 
  573.                   determine if the mouse movement represents a logical value 
  574.                   change and move the grab bar accordingly.
  575.  
  576.    Called By:     ILineWndProc, in response to a WM_MOUSEMOVE message.
  577.  
  578.    See Also:      OnLButtonDown, OnLButtonUp.
  579.  
  580.    Note:          This function has multiple return points.
  581.  
  582.    Note:          Since we have captured the mouse, we receive mouse msgs
  583.                   even when the mouse is outside our client area, but still
  584.                   in client coordinates. Thus we can have negative mouse
  585.                   coordinates. That is why we convert the lParam of the
  586.                   mouse msg into a POINTS structure rather than 2 WORDS.
  587.                   
  588.                    
  589.    Internals:     Remember that an IntervalLine can only take on integral
  590.                   values in the user-supplied range. Therefore we do our
  591.                   movement calculation in user values, not pixels. We
  592.                   determine what the logical value would be for the previous
  593.                   (last mouse move) and current mouse position. If these
  594.                   LOGICAL values differ, we attempt an adjustment of the
  595.                   grab bar by that logical amount.  This way the grab 
  596.                   values assume on integral positions and the calculations
  597.                   are simplified. 
  598.  
  599.                   If we calculated by pixel movement, and then shifted the 
  600.                   bar into the nearest integal position, we would encounter 
  601.                   rounding problems. In particular, when tracking the center 
  602.                   grab bar, if we moved both start and stop by the same 
  603.                   amount of PIXELS, then converted to LOGICAL values, we 
  604.                   might find our center bar shrinking and growing while
  605.                   the bar moves.
  606. */
  607.    {
  608.    int            iMousePrevious, iMouseCurrent ;
  609.    int            iMouseMove ;
  610.    PILINE         pILine ;
  611.    HDC            hDC ;
  612.  
  613.    //=============================//
  614.    // Are we tracking?            //
  615.    //=============================//
  616.  
  617.    pILine = ILData (hWnd) ;
  618.    if (ILMode (pILine) == ILModeNone)
  619.       return ;
  620.  
  621.    //=============================//
  622.    // Calc LOGICAL mouse movement //
  623.    //=============================//
  624.  
  625.    ptsMouse.x = PinInclusive ((INT)ptsMouse.x, 
  626.                               (INT)pILine->rectBorder.left, 
  627.                               (INT)pILine->rectBorder.right) ;
  628.  
  629.    iMousePrevious = ILPixelToValue (pILine, pILine->ptsMouse.x) ;
  630.    iMouseCurrent = ILPixelToValue (pILine, ptsMouse.x) ;
  631.  
  632.    iMouseMove = iMouseCurrent - iMousePrevious ;
  633.    if (!iMouseMove)   
  634.       return ;
  635.  
  636.    //=============================//
  637.    // Move grab bar positions     //
  638.    //=============================//
  639.  
  640.    switch (ILMode (pILine))
  641.       {  // switch   
  642.       case ILModeLeft:
  643.          ILStart (pILine) += iMouseMove ;
  644.          ILStart (pILine) = min (ILStart (pILine), ILStop (pILine) - 1) ;
  645.          break ;
  646.  
  647.       case ILModeCenter:
  648.          // Before we slide the center grab bar we need to see if the 
  649.          // desired movement amount would send either end out of bounds,
  650.          // and reduce the movement accordingly.
  651.  
  652.          if (ILStart (pILine) + iMouseMove < ILBegin (pILine))
  653.             iMouseMove = ILBegin (pILine) - ILStart (pILine) ;
  654.          if (ILStop (pILine) + iMouseMove > ILEnd (pILine))
  655.             iMouseMove = ILEnd (pILine) - ILStop (pILine) ;
  656.  
  657.          ILStart (pILine) += iMouseMove ;
  658.          ILStop (pILine) += iMouseMove ;
  659.          break ;
  660.  
  661.       case ILModeRight:
  662.          ILStop (pILine) += iMouseMove ;
  663.          ILStop (pILine) = max (ILStart (pILine) + 1, ILStop (pILine)) ;
  664.          break ;
  665.       }  // switch
  666.  
  667.  
  668.    //=============================//
  669.    // Keep grab bars in range     //
  670.    //=============================//
  671.  
  672.  
  673.    ILStart (pILine) = PinInclusive (ILStart (pILine),
  674.                                     ILBegin (pILine), ILEnd (pILine)) ;
  675.    ILStop (pILine) = PinInclusive (ILStop (pILine),
  676.                                    ILBegin (pILine), ILEnd (pILine)) ;
  677.  
  678.    //=============================//
  679.    // Determine pixel pos, draw   //
  680.    //=============================//
  681.  
  682.    ILCalcPositions (hWnd, pILine) ;
  683.  
  684.    hDC = GetDC (hWnd) ;
  685.    ILDraw (hDC, pILine, &pILine->rectBorder) ;
  686.    ReleaseDC (hWnd, hDC) ;
  687.  
  688.    pILine->ptsMouse = ptsMouse ;
  689.    ILNotifyChange (hWnd, pILine) ;
  690.    }  // OnMouseMove
  691.  
  692.  
  693. void static OnLButtonDown (HWND hWnd, 
  694.                            POINTS ptsMouse)
  695.    {
  696.    PILINE         pILine ;
  697.    POINT          ptMouse ;
  698.  
  699.    pILine = ILData (hWnd) ;
  700.  
  701.    pILine->ptsMouse = ptsMouse ;
  702.    ptMouse.x = ptsMouse.x ;
  703.    ptMouse.y = ptsMouse.y ;
  704.  
  705.    if (PtInRect (&pILine->rectLeftBk, ptMouse))
  706.       ILPageLeftRight (hWnd, pILine, TRUE) ;
  707.  
  708.    else if (PtInRect (&pILine->rectRightBk, ptMouse))
  709.       ILPageLeftRight (hWnd, pILine, FALSE) ;
  710.  
  711.    else if (PtInRect (&pILine->rectLeftGrab, ptMouse))
  712.       {
  713.       ILMode (pILine) = ILModeLeft ;
  714.       StartGrab (hWnd, pILine) ;
  715.       }
  716.  
  717.    else if (PtInRect (&pILine->rectRightGrab, ptMouse))
  718.       {
  719.       ILMode (pILine) = ILModeRight ;
  720.       StartGrab (hWnd, pILine) ;
  721.       }
  722.  
  723.    else if (PtInRect (&pILine->rectCenterGrab, ptMouse))
  724.       {
  725.       ILMode (pILine) = ILModeCenter ;
  726.       StartGrab (hWnd, pILine) ;
  727.       }
  728.    }
  729.  
  730.  
  731. void static OnSize (HWND hWnd, WORD xWidth, WORD yHeight)
  732.    {  // OnSize
  733.    PILINE         pILine ;
  734.  
  735.    pILine = ILData (hWnd) ;
  736.  
  737.    ILCalcPositions (hWnd, pILine) ;
  738.    }  // OnSize
  739.  
  740.  
  741. //==========================================================================//
  742. //                             Exported Functions                           //
  743. //==========================================================================//
  744.  
  745.  
  746. LONG FAR PASCAL ILineWndProc (HWND hWnd,
  747.                               unsigned msg,
  748.                               WPARAM wParam,
  749.                               LONG lParam)
  750. /*
  751.    Note:          This function must be declared in the application's
  752.                   linker-definition file, perfmon.def file.
  753. */
  754.    {  // ILineWndProc
  755.    BOOL           bCallDefWindowProc ;
  756.    POINTS         ptsMouse ;
  757.    LONG           lReturnValue ;
  758.  
  759.    bCallDefWindowProc = FALSE ;
  760.    lReturnValue = 0L ;
  761.  
  762.    switch (msg)
  763.       {  // switch
  764.       case WM_CREATE:
  765.          OnCreate (hWnd) ;
  766.          break ;
  767.  
  768.       case WM_DESTROY:
  769.          OnDestroy (hWnd) ;
  770.          break ;
  771.  
  772.       case WM_LBUTTONDOWN:
  773.          // See the note in OnMouseMove for why we are using POINTS
  774.          ptsMouse = MAKEPOINTS (lParam) ;
  775.          OnLButtonDown (hWnd, ptsMouse) ;
  776.          break ;
  777.  
  778.       case WM_LBUTTONUP:
  779.          OnLButtonUp (hWnd) ;
  780.          break ;
  781.  
  782.       case WM_MOUSEMOVE:
  783.          // See the note in OnMouseMove for why we are using POINTS
  784.          ptsMouse = MAKEPOINTS (lParam) ;
  785.          OnMouseMove (hWnd, ptsMouse) ;
  786.          break ;
  787.  
  788.       case WM_PAINT:
  789.          OnPaint (hWnd) ;
  790.          break ;
  791.  
  792.       case WM_SIZE:
  793.          OnSize (hWnd, LOWORD (lParam), HIWORD (lParam)) ;
  794.  
  795.       default:
  796.          bCallDefWindowProc = TRUE ;
  797.       }  // switch
  798.  
  799.    if (bCallDefWindowProc)
  800.       lReturnValue = DefWindowProc (hWnd, msg, wParam, lParam) ;
  801.  
  802.    return (lReturnValue) ;
  803.    }  // ILineWndProc
  804.  
  805.  
  806.  
  807. BOOL ILineInitializeApplication (void)
  808. /*
  809.    Effect:        Perform all initializations required before an application
  810.                   can create an IntervalLine. In particular, register the 
  811.                   IntervalLine window class.
  812.  
  813.    Called By:     The application, in its InitializeApplication routine.
  814.  
  815.    Returns:       Whether the class could be registered.
  816. */
  817.    {  // ILineInitializeApplication
  818.    WNDCLASS       wc ;
  819.  
  820.    wc.style =           dwILineClassStyle ;
  821.    wc.lpfnWndProc =     ILineWndProc ;
  822.    wc.cbClsExtra =      iILineClassExtra ;
  823.    wc.cbWndExtra =      iILineWindowExtra ;
  824.    wc.hInstance =       hInstance ;
  825.    wc.hIcon =           NULL ;
  826.    wc.hCursor =         LoadCursor (NULL, IDC_ARROW) ;
  827.    wc.hbrBackground =   NULL ;
  828.    wc.lpszMenuName =    NULL ;
  829.    wc.lpszClassName =   szILineClass ;
  830.  
  831.    return (RegisterClass (&wc)) ;
  832.    }  // ILineInitializeApplication
  833.  
  834.  
  835. void ILineSetRange (HWND hWnd, int iBegin, int iEnd)
  836.    {  // ILineSetRange
  837.    PILINE         pILine ;
  838.  
  839.    pILine = ILData (hWnd) ;
  840.  
  841.    ILBegin (pILine) = iBegin ;
  842.    ILEnd (pILine) = iEnd ;
  843.  
  844.    ILCalcPositions (hWnd, pILine) ;
  845.    }  // ILineSetRange
  846.  
  847.  
  848. void ILineSetStart (HWND hWnd, int iStart)
  849.    {  // ILineSetStart
  850.    PILINE         pILine ;
  851.  
  852.    pILine = ILData (hWnd) ;
  853.  
  854.    iStart = PinInclusive (iStart, ILBegin (pILine), ILEnd (pILine)) ;
  855.    ILStart (pILine) = iStart ;
  856.  
  857.    ILCalcPositions (hWnd, pILine) ;
  858.    }  // ILineSetStart
  859.  
  860.  
  861.  
  862. void ILineSetStop (HWND hWnd, int iStop)
  863.    {  // ILineSetStop
  864.    PILINE         pILine ;
  865.  
  866.    pILine = ILData (hWnd) ;
  867.  
  868.    iStop = PinInclusive (iStop, ILBegin (pILine), ILEnd (pILine)) ;
  869.    ILStop (pILine) = iStop ;
  870.  
  871.    ILCalcPositions (hWnd, pILine) ;
  872.    }  // ILineSetStop
  873.  
  874.  
  875. int ILineXStart (HWND hWnd)
  876.    {
  877.    PILINE         pILine ;
  878.  
  879.    pILine = ILData (hWnd) ;
  880.  
  881.    return (pILine->rectLeftGrab.left) ;
  882.    }
  883.  
  884.  
  885. int ILineXStop (HWND hWnd)
  886.    {
  887.    PILINE         pILine ;
  888.  
  889.    pILine = ILData (hWnd) ;
  890.  
  891.    return (pILine->rectRightGrab.right) ;
  892.    }
  893.  
  894.  
  895. int ILineStart (HWND hWnd)
  896.    {
  897.    PILINE         pILine ;
  898.  
  899.    pILine = ILData (hWnd) ;
  900.  
  901.    return  (ILStart (pILine)) ;
  902.    }
  903.  
  904.  
  905. int ILineStop (HWND hWnd)
  906.    {
  907.    PILINE         pILine ;
  908.  
  909.    pILine = ILData (hWnd) ;
  910.  
  911.    return  (ILStop (pILine)) ;
  912.    }
  913.  
  914.  
  915.  
  916.